package proxynew;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;

import net.jxta.discovery.DiscoveryService;
import net.jxta.document.AdvertisementFactory;
import net.jxta.endpoint.ByteArrayMessageElement;
import net.jxta.endpoint.Message;
import net.jxta.id.IDFactory;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.pipe.InputPipe;
import net.jxta.pipe.PipeID;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeService;
import net.jxta.platform.NetworkManager;
import net.jxta.protocol.PipeAdvertisement;

public class PipeMsgListener extends Thread implements net.jxta.pipe.PipeMsgListener {
	public static String PIPE_NAME = "Multicast proxy";
	private static PipeID pipeId = IDFactory.newPipeID(PeerGroupID.defaultNetPeerGroupID);
	
	private NetworkManager networkManager;
	
	public PipeMsgListener(NetworkManager networkManager) {
		this.networkManager = networkManager;
	}

	public void run() {
		// get the pipe service, and discovery
		PipeService pipeService = networkManager.getNetPeerGroup().getPipeService();
		DiscoveryService discovery = networkManager.getNetPeerGroup().getDiscoveryService();
		try {
			InputPipe inputPipe = pipeService.createInputPipe(getPipeAdvertisement(), this);
			System.out.println("Pipe criado: " + inputPipe.getPipeID());
			
			long lifetime = 60 * 2 * 1000L;
			long expiration = 60 * 2 * 1000L;
			long waittime = 60 * 3 * 1000L;
			try {
			    while (true) {
			        PipeAdvertisement pipeAdv = getPipeAdvertisement();
			        // publish the advertisement with a lifetime of 2 mintutes
			        System.out.println("PipeMsgListener: Publicando pipe com tempo de vida  :" + lifetime + " expiracao " + expiration);
			        //System.out.println(pipeAdv.toString());
			        discovery.publish(pipeAdv, lifetime, expiration);
			        discovery.remotePublish(pipeAdv, expiration);
			        try {
			            System.out.println("PipeMsgListener: Dormindo por " + waittime);
			            Thread.sleep(waittime);
			        } catch (Exception e) {
			            //ignored
			        }
			    }
			} catch (Exception e) {
			    e.printStackTrace();
			}

			
		} catch (IOException e) {
			System.err.println("PipeMsgListener: Nao pode criar pipe, saindo...");
			e.printStackTrace();
		}		
	}
	
	public static PipeID getPideID() {
		return PipeMsgListener.pipeId;
	}

	/**
	 * Creates a pipe advertisement
	 * 
	 * @return a Pipe Advertisement
	 */
	public static PipeAdvertisement getPipeAdvertisement() {
		PipeAdvertisement advertisement = (PipeAdvertisement) AdvertisementFactory
				.newAdvertisement(PipeAdvertisement.getAdvertisementType());
		advertisement.setPipeID(getPideID());
		advertisement.setType(PipeService.UnicastType);
		advertisement.setName(PipeMsgListener.PIPE_NAME);
		return advertisement;
	}

	@Override
	public void pipeMsgEvent(PipeMsgEvent event) {
		String source = event.getSource().toString();
		String pipeID = event.getPipeID().toString();
		System.out.println("PipeMsgListener: Mensagem recebida de " + source + " no pipe " + pipeID);
		
		// faz o parse da mensagem
		Message message = event.getMessage();
//		StringMessageElement groupElement = (StringMessageElement) message.getMessageElement("group");
		ByteArrayMessageElement data = (ByteArrayMessageElement) message.getMessageElement("data");
		byte[] buffer = data.getBytes();
		String multicastGroup = new String (message.getMessageElement("group").getBytes(false));
		
		String ip = multicastGroup.split(":")[0];
		String port = multicastGroup.split(":")[1];
		
		if (!MessageCache.getInstance().isInCache(multicastGroup, buffer)) {	
			InetAddress ia;
			try {
				ia = InetAddress.getByName(ip);

				MulticastSocket ms = new MulticastSocket();
				ms.joinGroup(ia);
				ms.setTimeToLive(1);

				DatagramPacket dp = new DatagramPacket(buffer, buffer.length, ia, Integer.parseInt(port));
	
				System.out.println("PipeMsgListener: Encaminhando [" + buffer + "] para grupo " + ip + " porta " + port);
				ms.send(dp);
				MessageCache.getInstance().addMessageToCache(multicastGroup, buffer);
			} catch (UnknownHostException e) {
				System.err.println("PipeMsgListener: Erro nos parâmetros: " + e.getMessage());
				e.printStackTrace();
			} catch (IOException e) {
				System.err.println("PipeMsgListener: Erro no envio da mensagem. Ip = [" + ip + "] porta =[" + port + "]");
				e.printStackTrace();
			}
		}
	}
			
/*			
		    // Obtain the message from the event
		    msg = event.getMessage();
		    if (msg == null) {
		        System.out.println("Received an empty message");
		        return;
		    }
		    // dump the message content to screen
		    printMessageStats(msg, true);
		} catch (Exception e) {
		    e.printStackTrace();
		    return;
		}
		// get all the message elements
		Message.ElementIterator en = msg.getMessageElements();
		if (!en.hasNext()) {
		    return;
		}
		// get the message element in the name space PipeClient.MESSAGE_NAME_SPACE
		MessageElement msgElement = msg.getMessageElement(null, null); //PipeClient.MESSAGE_NAME_SPA
		// Get message
		if (msgElement.toString() == null) {
		    System.out.println("null msg received");
		} else {
		    Date date = new Date(System.currentTimeMillis());
		    System.out.println("Message received at :" + date.toString());
		    System.out.println("Message created at :" + msgElement.toString());
		}
	}
*/
}
